import app, { xlsxCfgNames } from "../../app";
import god from "../../god";
import { group, rank_type, taskKey } from "../../shared/interface";
import { Tpl_battleEnd, Tpl_battleLog, template } from "../../shared/master/MsgAction";
import { bag } from "../bag/bag";
import battlefield from "../fight/battle/battlefield";
import { baseBody } from "../fight/body/baseBody";
import { enemy } from "../fight/body/enemy";
import { pet } from "../fight/body/pet";
import { player, wallet_key } from "../fight/body/player";
import { SKILL } from "../fight/skill/SK_active";
import { logger } from "../server/logger";
import manage_task from "../../master/model/manage/manage_task";
import word from "./word";
import { npc } from "../fight/body/npc";

export default class cell {
    uuid: string = app.v4();
    x: number = 0;
    y: number = 0;
    private word!: word;
    private bodys: (baseBody | undefined)[] = [];
    private battlefields: Map<string, battlefield> = new Map();
    private breakOut: boolean = true;
    private bodySize: number = 0;
    private lastCreateEnemy = 0;
    private pvp: Boolean = true;
    private activeAttack: Boolean = false;
    /**
     * 宝箱数量
     */
    private giftBox: number = 0;
    /**
     * 湖水平方
     */
    private water: number = 0;
    /**
     * 记录区域玩家来过的次数
     */
    private comingPlayerMap: Map<string, number> = new Map();
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;

        if (app.random(0, 100) <= 20) {
            this.water = app.random(1, 1000)
        }
    }
    get_water() {
        if (!this.word.cfg.fishing) {
            return 0;
        }
        return this.water;
    }
    get_battleSize() {
        return this.battlefields.size
    }
    get_giftBox() {
        return this.giftBox;
    }
    addGfitBox(num: number = 1) {
        this.giftBox += 1;
    }
    async openGift(body: player) {
        if (this.giftBox <= 0) {
            return;
        }

        if (body.is_die()) {
            body.sendMsg(template.default, `请先[复活]后再打开宝箱`)
            return;
        }
        let res = body.check_wallet(0, 0, [{ id: 'prop-22', v: 1 }], false, `开启宝箱`, true);
        if (!res.state) {
            return;
        }
        await body.sendMsg(template.default, "满怀期待的打开宝箱中...5s")
        this.activeAttackPlayer();
        await new Promise(rs => { setTimeout(rs, 5000) });
        if (this.giftBox <= 0) {
            body.sendMsg(template.default, "纳尼?宝箱不见了！")
            return;
        }
        if (body.get_battle()) {
            body.sendMsg(template.default, "正在战斗中,宝箱开启失败")
            return;
        }
        if (body.getPosition().uuid != this.uuid) {
            body.sendMsg(template.default, "已离开宝箱位置,宝箱开启失败")
            return;
        }

        this.giftBox -= 1;
        let _word = this.word;
        let items = god.getRandomItem_score(app.generateRandom(this.word.cfg.fallScoreMin, this.word.cfg.fallScoreMax), `${_word.name}-宝箱掉落`);
        manage_task.event(taskKey.成功打开宝箱, 1, body)
        let temp = '宝箱开启完毕！你获得:\n';
        for (let i = 0; i < items.length; i++) {
            const element = items[i];
            if (!element) {
                continue;
            }
            temp += `${element.getStyleName()}X${element.num}\n`
        }
        if (this.giftBox) {
            temp += `当前位置还有${this.giftBox}个宝箱！`
        }
        body.sendMsg(template.default, temp);

        for (let i = 0; i < items.length; i++) {
            const element = items[i];
            if (element) {
                body.getBag().add(element)
            }
        }
    }
    // 销毁
    destroy() {
        this.bodys.forEach((e) => {
            if (e instanceof player) {
                return;
            }
            e?.destroy();
        })
        if (this.battlefields.size != 0) {
            debugger;
        }

    }
    set_activeAttack(b: number) {
        this.activeAttack = !!b;
    }
    setPVP(b: boolean) {
        this.pvp = b;
    }
    /**
     * 怪物主动向玩家发起一次攻击
     */
    activeAttackPlayer() {
        /**
         * 1.分析出 怪物组和 玩家组
         * 2.如果正在战斗的单位则过滤
         * 3.怪物1  攻击 玩家1  拿到战场
         * 4.剩余怪物 全部加入战场 主场
         * 5.剩余玩家 全部加入战场 客场
         */
        let enemys = this.bodys.filter((item) => { if ((item instanceof enemy) && !item.get_battle()) { return item } });
        let players = this.bodys.filter((item) => { if ((item instanceof player) && !item.get_battle()) { return item } });
        if (!enemys.length || !players.length) {
            return;
        }
        let battles: battlefield | undefined;
        for (let i = 0; i < enemys.length; i++) {
            const element = enemys[i] as enemy;
            if (i == 0) {
                const tag = players[0] as player;
                battles = this.attack(element.uuid, tag.uuid);
                continue;
            }
            if (!battles) {
                debugger;
                return;
            }
            battles.join(element, group.客场);
        }
        for (let i = 1; i < players.length; i++) {
            const element = players[i] as player;
            if (!battles) {
                debugger;
                return;
            }
            battles.join(element, group.主场);
        }
    }
    /**
     * 查看此单位是否可以在此格子离开
     * @returns 
     */
    haveBreakOut(id: string) {
        let body = this.get_Body_id(id);
        if (!body) {
            return true;
        }
        let battle = body.get_battle();
        if (!battle) {
            return true;
        }
        return this.breakOut;
    }
    getBodys() {
        let list: (baseBody | undefined)[] = []
        for (let index = 0; index < this.bodys.length; index++) {
            const element = this.bodys[index];
            if (!element) {
                list.push(undefined)
                continue;
            }
            if (element instanceof enemy) {
                if (element.is_die() && !element.get_battle()) {
                    element?.destroy();
                    list.push(undefined);
                    continue;
                }
            }
            list.push(element)
        }
        return this.bodys;
    }
    haveNpc(name: string) {
        let jude = false;
        for (let index = 0; index < this.bodys.length; index++) {
            const element = this.bodys[index];
            if (!(element instanceof npc)) {
                continue;
            }
            if (element.name != name) {
                continue;
            }
            jude = true;
            break;
        }
        return jude;
    }
    setWord(e: word) {
        this.word = e;
        if (e.cfg.giftBox) {
            if (app.random(0, 100) <= e.cfg.giftBox) {
                this.giftBox = app.generateRandom(1, 2)
            }
        }
    }
    getWord() {
        return this.word;
    }
    attack(create_id: string, tag_id: string) {
        // 检测目标是否在战斗中，如果在战斗中那么直接加入到目标对立方
        let p1 = this.get_Body_id(create_id);
        let p2 = this.get_Body_id(tag_id);
        if (!p1 || !p2) {
            debugger;
            return;
        }
        if (p1.uuid == p2.uuid) {
            if (p1 instanceof player) {
                p1.sendMsg(template.default, '你不能攻击你自己');
            }
            return;
        }
        if (!this.pvp && p1 instanceof player && p2 instanceof player) {
            p1.sendMsg(template.default, '此位置禁止PVP');
            return;
        }
        if (p1 instanceof player && p2 instanceof player) {
            if (p1.team_id.length > 2 && p1.team_id == p2.team_id) {
                p1.sendMsg(template.default, '你不能向小队成员攻击');
                return;
            }
        }

        let p1_bt = p1.get_battle();
        let p2_bt = p2.get_battle();
        if (p1_bt && !p2_bt) {
            // 战斗发起方正在战斗，被攻击方没有战斗
            p1_bt.join(p2, group.主场);
            return p1_bt;
        }
        if (!p1_bt && p2_bt) {
            // 战斗发起方正在战斗，被攻击方没有战斗
            if (p2_bt.checkSpecial()) {
                if (p1 instanceof player) {
                    p1.sendMsg(template.default, '对方处于特殊战中,你无法加入战斗');
                }
                return;
            }
            p2_bt.join(p1, group.客场);
            return p2_bt;
        }

        if (!p1.get_battle() && !p2.get_battle()) {
            // 都没有在战斗中  创建战场开始战斗
            let battles = new battlefield();
            this.battlefields.set(battles.id, battles);

            battles.join(p1, group.客场);
            battles.join(p2, group.主场);
            battles.start();
            battles.setEndCall((a, b,c) => { this.onBattleEnd(a, b,c) })
            battles.setOutEndCall((a, b) => { this.onBattleOutEnd(a, b) })
            battles.setKillCall((a, b, c, d) => { this.onBattleKill(a, b, c, d) })
            p1.sendMsg(template.default, `[${p1.nickName}]战斗开始!接下来你可以直接发送技能名称来决定下回合释放技能!回合倒计时:${Number(god.getServerCfgItem('battle_roundTime').a)}秒`)
            p2.sendMsg(template.default, `${p1.nickName}主动对你发起了攻击!`)
            return battles;
        }


    }
    private onBattleOutEnd(endBattle: battlefield, outBody: baseBody) {
        this.battlefields.delete(endBattle.id);
        endBattle.destroy();
    }
    /**
     * 战斗结束
     * 需要知道哪方胜利
     * 需要知道奖励是什么， 具体数量
     */
    private onBattleEnd(endBattle: battlefield, winGroup: group,log:Tpl_battleLog) {
        console.log(`战场:${endBattle.id},${winGroup}方胜利`);

        let allBody = endBattle.getBody_all();
        let winBodys = endBattle.getBody_all_group(winGroup);
        let dieBodys = endBattle.getBody_all_group(app.getAbsGroup(winGroup));
        // 消息推送模板
        let obj: Tpl_battleEnd = {
            round: endBattle.round,
            winGroup: winGroup,
            gifts: []
        }
        // 奖励分配
        /**
         * 怪物死亡 掉落金币 钻石
         * 所有胜利方玩家均分 金币
         * 玩家死亡 掉落金币 钻石
         */
        let diamond = 0;
        let exp = 0;
        for (let index = 0; index < dieBodys.length; index++) {
            const element = dieBodys[index];
            if (element instanceof enemy) {
                exp += app.random(1, element.leve.num);
            }
            if (element instanceof player) {
                diamond += 1;
            }
        }
        let winPlayers: player[] = [];
        let winExpBodys: baseBody[] = []
        for (let index = 0; index < winBodys.length; index++) {
            const element = winBodys[index];
            if (element instanceof player) {
                winPlayers.push(element)
                winExpBodys.push(element);
            }
        }
        let avExp = Math.ceil(exp / winExpBodys.length);

        winExpBodys.forEach(element => {
            element.addExp(avExp);
            obj.gifts.push({user_name:element.nickName,user_id:element.uuid,info:{exp:avExp}})
        })
        log.end = obj;
        for (let i = 0; i < allBody.length; i++) {
            const element = allBody[i];
            if (element instanceof player) {
                element.sendMsg(template.Battle_log, log);
            }
        }
        endBattle.destroy();
        this.battlefields.delete(endBattle.id);
    }
    /**
     * 监听单位击杀情况
     * @param idx 
     * @returns 
     */
    private onBattleKill(battle: battlefield, winBody: baseBody, dieBody: baseBody, sk: SKILL) {
        logger.debug(`${winBody.nickName}使用${sk.rename} 击杀了 ${dieBody.nickName}`)
        // TODO:详细分析
        manage_task.event(taskKey.击杀普通怪物, 1, winBody, dieBody)
        dieBody.get_battle()?.addRoundLog(
            dieBody.get_Master().uuid,
            winBody.nickName,
            `☠️${dieBody.nickName}`,
            []
        )
        if (dieBody instanceof enemy) {
            let _winBody = winBody.get_Master();
            _winBody.addExp(dieBody.leve.num);
            const bag = winBody.getBag() as bag;
            if (!bag) {
                return;
            }
            if (_winBody instanceof player) {
                if (_winBody.getWordTask()?.end) {
                    winBody.get_battle()?.addRoundLog(
                        _winBody.uuid,
                        winBody.nickName,
                        `☠️${dieBody.nickName}`,
                        []
                    )
                    return
                }
            }
            let info = dieBody.RandomFallDown_v2()
            let gift: any = [];
            if (app.random(0, 100) < this.word.cfg.fallDownRang) {
                let item = god.getRandomItem_v2Tname(info.score, info.name, xlsxCfgNames.怪物掉落配置, true)
                gift.push({ name: item.getStyleName(), cont: 1 })
                bag.add(item);
            }
            winBody.get_battle()?.addRoundLog(
                _winBody.uuid,
                winBody.nickName,
                `☠️${dieBody.nickName}`,
                gift
            )

        }
    }
    get_Body_index(idx: number) {
        return this.bodys[idx];
    }
    /**
     * 返回当前存活且未战斗的所有单位
     */
    get_Body_idle(): baseBody[] {
        let arry = this.bodys.filter((item) => {
            return item && !item.is_die() && !item.get_battle() && !(item instanceof pet)
        })
        return arry as baseBody[]
    }
    get_Body_weak() {
        let lowestLeveItem = this.bodys.reduce((lowest, item) => {
            // 确保item存在，没有标记为is_die()，并且有leve属性
            if (item && !item.is_die()) {
                // 如果当前没有最低的，或者当前项的leve小于目前记录的最低leve，更新最低leve的记录
                if (!lowest || item.leve < lowest.leve) {
                    return item;
                }
            }
            return lowest;
        }, undefined);
        return lowestLeveItem
    }
    get_Body_id(id: string) {
        let idx = this.bodys.findIndex((item) => { return item && item.uuid == id });
        return this.bodys[idx];
    }
    createEnemy(leve: number) {
        if (!this.getWord()) {
            return undefined;
        }
        let w = this.getWord();
        let enemyMap = this.getWord()._enemyMap;
        if (enemyMap.size == 0) {
            return undefined
        }
        let create_cont = this.bodySize <= 0 ? app.random(1, 10) : app.random(1, 3)
        for (let i = 0; i < create_cont; i++) {
            let _leve = app.generateRandom(Math.ceil(leve * 0.5), Math.ceil(leve * 1.5))
            let e = app.createUnity('-1', _leve, enemyMap, _leve * 0.5);
            if (!e) {
                debugger;
                return undefined;
            }
            e.setPosition(this);
        }

    }
    add(body: baseBody) {
        if (body instanceof player &&  this.checkCreateEnemy()) {
            try {
                this.createEnemy(body.leve.num);
            } catch (error) {
                debugger
            }
        }
        this.bodySizeChange(1);
        this.bodys.push(body);
        console.log(`${body.name}进入${this.x}_${this.y}`)
        setTimeout(() => {
            this.checActvieAttack(body);
        }, 100)
        if (body instanceof player) {
            this.comingPlayer(body);
        }
    }
    private comingPlayer(body: player) {
        let last = this.comingPlayerMap.get(body.uuid) || 0;
        if (!last) {
            manage_task.event(taskKey.移动到未知位置, 1, body)
            body.log.add(rank_type.步数, 1)
        }
        this.comingPlayerMap.set(body.uuid, last + 1);
    }
    private checActvieAttack(body: baseBody) {
        if (!this.activeAttack) {
            if (app.random(0, 100) > god.getServerCfgItem('activeAttack').b) {
                return;
            }
            if (body.leve.num < 100) {
                return;
            }
        }
        if (this.bodySize == 0) {
            return;
        }
        if (!(body instanceof player)) {
            return;
        }

        let enemys = this.bodys.filter((item) => { if ((item instanceof enemy) && !item.get_battle()) { return item } });
        if (enemys.length == 0) {
            return;
        }
        for (let i = 0; i < enemys.length; i++) {
            const element = enemys[i] as enemy;
            this.attack(element.uuid, body.uuid)
        }

    }
    private checkCreateEnemy() {
        if (Date.now() > this.lastCreateEnemy) {
            this.lastCreateEnemy = Date.now() + 5000;
            return true;
        }
        return false;
    }
    private bodySizeChange(change: number) {
        this.bodySize += change;
        if (this.bodySize == 0) {
            this.bodys = []
        }
    }
    del(body: baseBody, force?: boolean) {
        if (!this.haveBreakOut(body.uuid) && !force) {
            logger.error('非法移动');
            return false;
        }
        // 退出战场
        let battle = body.get_battle();
        if (battle) {
            battle.out(body);
        }
        let idx = this.bodys.findIndex((item) => { return item && item.uuid == body.uuid });
        if (idx != -1) {
            this.bodys[idx] = undefined;
            this.bodySizeChange(-1);
            console.log(`离开格子 - ${body.name} - ${this.x}_${this.y}`)
        }
        return true;
    }
}